# -*- coding: utf-8 -*-
#--------------------------------------------------------------------------
# Copyright (c) 2009 Barry Schwartz
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

#--------------------------------------------------------------------------
#
# Low-level access to the FontForge library
#

cimport python

cdef extern from *:
    ctypedef unsigned char uint8
    ctypedef short int int16
    ctypedef unsigned short int uint16
    ctypedef unsigned int uint32

cdef extern from "string.h":
    int strcmp(char *s1, char *s2)

cdef extern from "splinefont.h":

    ctypedef double real
    cdef struct fontviewbase
    cdef struct kernpair
    cdef struct kernclass
    cdef struct otlookup
    cdef struct generic_fpst
    cdef struct generic_asm
    cdef struct splinechar
    cdef struct splinecharlist
    cdef struct splinefont

    cdef enum ps_flags:
        ps_flag_nohintsubs = 0x10000
        ps_flag_noflex = 0x20000
        ps_flag_nohints = 0x40000
        ps_flag_restrict256 = 0x80000
        ps_flag_afm = 0x100000
        ps_flag_pfm = 0x200000
        ps_flag_tfm = 0x400000
        ps_flag_round = 0x800000

        # CFF fonts are wrapped up in some postscript sugar -- unless
        # they are to go into a pdf file or an otf font.
        ps_flag_nocffsugar = 0x1000000

        # In type42 cid fonts we sometimes want an identity map from
        # gid to cid.
        ps_flag_identitycidmap = 0x2000000

        ps_flag_afmwithmarks = 0x4000000
        ps_flag_noseac = 0x8000000
        ps_flag_outputfontlog = 0x10000000
        ps_flag_mask = (ps_flag_nohintsubs | ps_flag_noflex | ps_flag_afm | ps_flag_pfm | ps_flag_tfm | ps_flag_round)

    ctypedef struct PyFF_Glyph:
        splinechar *sc

    ctypedef struct PyFF_Font:
        fontviewbase *fv

    cdef enum:
        tex_unset
        tex_text
        tex_math
        tex_mathext

    cdef struct texdata:
        int tex_type "type"
        int params[22]

    cdef enum otlookup_type:
        ot_undef = 0            # Not a lookup type
        gsub_start         = 0x000 # Not a lookup type
        gsub_single        = 0x001
        gsub_multiple      = 0x002
        gsub_alternate     = 0x003
        gsub_ligature      = 0x004
        gsub_context       = 0x005
        gsub_contextchain  = 0x006
        # GSUB extension 7
        gsub_reversecchain = 0x008
        # mac state machines
        morx_indic         = 0x0fd
        morx_context       = 0x0fe
        morx_insert        = 0x0ff
        # *********************
        gpos_start         = 0x100 # Not a lookup type
        
        gpos_single        = 0x101
        gpos_pair          = 0x102
        gpos_cursive       = 0x103
        gpos_mark2base     = 0x104
        gpos_mark2ligature = 0x105
        gpos_mark2mark     = 0x106
        gpos_context       = 0x107
        gpos_contextchain  = 0x108
        # GPOS extension 9
        kern_statemachine  = 0x1ff

        # otlookup&0xff == lookup type for the appropriate table
        # otlookup>>8:     0=>GSUB, 1=>GPOS

    cdef enum otlookup_typemasks:
        gsub_single_mask        = 0x00001
        gsub_multiple_mask      = 0x00002
        gsub_alternate_mask     = 0x00004
        gsub_ligature_mask      = 0x00008
        gsub_context_mask       = 0x00010
        gsub_contextchain_mask  = 0x00020
        gsub_reversecchain_mask = 0x00040
        morx_indic_mask         = 0x00080
        morx_context_mask       = 0x00100
        morx_insert_mask        = 0x00200
        # *********************
        gpos_single_mask        = 0x00400
        gpos_pair_mask          = 0x00800
        gpos_cursive_mask       = 0x01000
        gpos_mark2base_mask     = 0x02000
        gpos_mark2ligature_mask = 0x04000
        gpos_mark2mark_mask     = 0x08000
        gpos_context_mask       = 0x10000
        gpos_contextchain_mask  = 0x20000
        kern_statemachine_mask  = 0x40000

    cdef enum pst_flags:
        pst_r2l = 1
        pst_ignorebaseglyphs = 2
        pst_ignoreligatures = 4,
        pst_ignorecombiningmarks = 8
        pst_usemarkfilteringset = 0x10
        pst_markclass = 0xff00
        pst_markset = 0xffff0000

    cdef struct vr:
        int16 xoff, yoff, h_adv_off, v_adv_off

    cdef struct lookup_subtable:
        char *subtable_name
        char *suffix #            # for gsub_single, used to find a default replacement
        int16 separation, minkern # for gpos_pair, used to guess default kerning values
        otlookup *lookup
        unsigned int unused
        unsigned int per_glyph_pst_or_kern
        unsigned int anchor_classes
        unsigned int vertical_kerning
        unsigned int ticked
        unsigned int kerning_by_touch # for gpos_pair, calculate kerning so that glyphs will touch
        unsigned int onlyCloser
        kernclass *kc
        generic_fpst *fpst
        generic_asm *sm   # Apple state machine; not implemented in kt.
        lookup_subtable *next

    cdef struct otlookup:
        otlookup *next
        otlookup_type lookup_type
        uint32 lookup_flags # Low order: traditional flags, High order: markset index, only meaningful if pst_usemarkfilteringset set
        char *lookup_name
        lookup_subtable *subtables

    cdef struct fpg:
        char *names, *back, *fore

    cdef struct fpc:
        int ncnt, bcnt, fcnt
        uint16 *nclasses, *bclasses, *fclasses, *allclasses

    cdef struct fpv:
        int ncnt, bcnt, fcnt
        char **ncovers, **bcovers, **fcovers

    cdef struct fpr:
        int always1, bcnt, fcnt
        char **ncovers, **bcovers, **fcovers
        char *replacements

    cdef union generic_fpst_union:
        fpg glyph
        fpc fpst_class "class"
        fpv coverage
        fpr rcoverage

    cdef struct seqlookup:
        int seq
        otlookup *lookup

    cdef struct fpst_rule:
        generic_fpst_union u
        int lookup_cnt
        seqlookup *lookups

    cdef struct DeviceTable

    cdef struct kernpair:
        lookup_subtable *subtable
        splinechar *sc
        int16 off
        uint16 kcid             # temporary value
        kernpair *next

    cdef struct kernclass:
        int first_cnt, second_cnt # Count of classes for first and second chars
        char **firsts  # list of a space separated list of char names
        char **seconds #  one entry for each class. Entry 0 is null
        #              #  and means everything not specified elsewhere
        lookup_subtable *subtable
        uint16 kcid    # Temporary value, used for many things briefly
        int16 *offsets # array of first_cnt*second_cnt entries
        kernclass *next

    cdef enum possub_type:
        pst_null
        pst_position
        pst_pair
        pst_substitution
        pst_alternate
        pst_multiple
        pst_ligature,
        pst_lcaret              # must be pst_max-1, see charinfo.c
        pst_max

        # These are not psts but are related so it's handly to have values for them
        pst_kerning = pst_max
        pst_vkerning
        pst_anchors

        # And these are fpsts
        pst_contextpos
        pst_contextsub
        pst_chainpos
        pst_chainsub
        pst_reversesub
        fpst_max

        # And these are used to specify a kerning pair where the current
        # char is the final glyph rather than the initial one.
        # A kludge used when cutting and pasting features.
        pst_kernback
        pst_vkernback

    cdef struct pst_pair_struct:
        char *paired
        vr *vr

    cdef struct pst_subs_struct:
        char *variant

    cdef struct pst_mult_struct:
        char *components

    cdef struct pst_lig_struct:
        char *components
        splinechar *lig

    cdef struct pst_lcaret_struct:
        int16 *carets
        int cnt        

    cdef union pst_union:
        vr pos
        pst_pair_struct pair
        pst_subs_struct subs
        pst_mult_struct mult, alt
        pst_lig_struct lig
        pst_lcaret_struct lcaret

    cdef struct generic_pst:
        unsigned int ticked
        uint8 pst_type "type"   # enum possub_type
        lookup_subtable *subtable
        generic_pst *next
        pst_union u

    cdef struct liglist:
        generic_pst *lig
        splinechar *first          # First component.
        splinecharlist *components # The other components.
        liglist *next
        int ccnt    # Component count (including the first component).

    cdef enum fpossub_format:
        pst_glyphs
        pst_class
        pst_coverage
        pst_reversecoverage
        pst_formatmax

    cdef struct generic_fpst:
        uint16 fpst_type "type" # enum possub_type
        uint16 format           # enum fpossub_format
        lookup_subtable *subtable
        generic_fpst *next
        uint16 nccnt, bccnt, fccnt
        uint16 rule_cnt
        char **nclass, **bclass, **fclass
        fpst_rule *rules
        uint8 ticked
        uint8 effectively_by_glyphs

    cdef struct splinechar:
        char *name
        int unicodeenc
        int orig_pos            # Original position in the glyph list.
        int16 width, vwidth
        splinefont *parent
        splinecharlist *dependents # The dependents list is a list of
                                   # all characters that reference
                                   # the current character directly.
        kernpair *kerns
        kernpair *vkerns
        generic_pst *possub # If we are a ligature then this tells us what.
                            # It may also contain a bunch of other stuff, now.
        liglist *ligofme # If this is the first character of a
                         # ligature then this gives us the list of
                         # possible ones. This field must be
                         # regenerated before the font is saved.
        int16 italic_correction

    cdef struct splinecharlist:
        splinechar *sc
        splinecharlist *next

    cdef struct splinefont:
        char *fontname, *fullname, *familyname, *weight
        char *copyright
        char *filename # sfd name. NULL if we open a font, that's origname
        char *defbasefilename
        char *version
        real italicangle, upos, uwidth # In font info
        int ascent, descent
        int uniqueid            # Not copied when reading in!!!!
        int glyphcnt, glyphmax  # allocated size of glyphs array
        splinechar **glyphs
        texdata texdata
        otlookup *gsub_lookups, *gpos_lookups

    bint SCRightToLeft(splinechar *sc)
    bint SCWorthOutputting(splinechar *sc)
    int SFFindGID(splinefont *sf, int unienc, char *name) # |unienc| == -1 to use |name|.
    otlookup *SFFindLookup(splinefont *sf, char *name)
    lookup_subtable *SFFindLookupSubtable(splinefont *sf, char *name)
    otlookup **SFLookupsInScriptLangFeature(splinefont *sf, int gpos, uint32 script, uint32 lang, uint32 feature)
    void SFLigaturePrepare(splinefont *sf)
    void SFLigatureCleanup(splinefont *sf)

cdef extern from "baseviews.h":
    cdef struct fontviewbase:
        splinefont *sf

cdef extern from "libff_types.h":
    ctypedef struct PyFF_Font:
        fontviewbase *fv

cdef inline splinefont *sf(obj):
    return (<PyFF_Font *> obj).fv.sf

cdef inline splinechar *sc(obj):
    return (<PyFF_Glyph *> obj).sc
